//-----------------------------------------------------------------------
// <copyright file="PropertiesAcceptanceTest.cs" company="NMock2">
//
//   http://www.sourceforge.net/projects/NMock2
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
// </copyright>
// This is the easiest way to ignore StyleCop rules on this file, even if we shouldn't use this tag:
// <auto-generated />
//-----------------------------------------------------------------------
namespace NMock2.AcceptanceTests
{
    using System;
    using NMock2.Internal;
    using NUnit.Framework;

    public interface IPersonRecord
    {
        string FirstName { get; set; }
        string LastName { get; set; }
    }

    public abstract class PersonRecord : IPersonRecord
    {
        public virtual string FirstName { get; set; }
        public abstract string LastName { get; set; }
    }
    
    [TestFixture]
    public class PropertiesAcceptanceTest : AcceptanceTestBase
    {
        [Test]
        public void CanExpectPropertyGetterOnInterface()
        {
            AssertCanExpectPropertyGetter(Mocks.NewMock<IPersonRecord>());
        }

        [Test, Class]
        public void CanExpectPropertyGetterOnClass()
        {
            AssertCanExpectPropertyGetter(Mocks.NewMock<PersonRecord>());
        }

        private void AssertCanExpectPropertyGetter(IPersonRecord personRecord)
        {
            Stub.On(personRecord).GetProperty("FirstName").Will(Return.Value("Fred"));
            Stub.On(personRecord).GetProperty("LastName").Will(Return.Value("Bloggs"));

            Verify.That(personRecord.FirstName, NMock2.Is.EqualTo("Fred"), "first name");
            Verify.That(personRecord.LastName, NMock2.Is.EqualTo("Bloggs"), "last name");
        }

        [Test]
        public void CanExpectPropertySetterOnInterface()
        {
            AssertCanExpectPropertySetter(Mocks.NewMock<IPersonRecord>());
        }

        [Test, Class]
        public void CanExpectPropertySetterOnClass()
        {
            AssertCanExpectPropertySetter(Mocks.NewMock<PersonRecord>());
        }

        private void AssertCanExpectPropertySetter(IPersonRecord personRecord)
        {
            Expect.Once.On(personRecord).SetProperty("FirstName").To("Fred");
            Expect.Once.On(personRecord).SetProperty("LastName").To("Bloggs");
            
            personRecord.FirstName = "Fred";
            personRecord.LastName = "Bloggs";
        }

        [Test]
        public void ErrorMessagesContainNameOfPropertyGetterNotHiddenMethodOnInterface()
        {
            AssertErrorMessagesContainNameOfPropertyGetterNotHiddenMethod(Mocks.NewNamedMock<IPersonRecord>("p"));
        }

        [Test, Class]
        public void ErrorMessagesContainNameOfPropertyGetterNotHiddenMethodOnClass()
        {
            AssertErrorMessagesContainNameOfPropertyGetterNotHiddenMethod(Mocks.NewNamedMock<PersonRecord>("p"));
        }

        private void AssertErrorMessagesContainNameOfPropertyGetterNotHiddenMethod(IPersonRecord personRecord)
        {
            SkipVerificationForThisTest();
            
            Stub.On(personRecord).GetProperty("FirstName").Will(Return.Value("Fred"));

            try
            {
                String.Intern(personRecord.LastName);
            }
            catch (ExpectationException e)
            {
                Assert.IsTrue(e.Message.IndexOf("get_FirstName()") < 0,
                    "message should not contain get_FirstName()\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("p.FirstName") >= 0,
                    "message should contain p.FirstName\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("get_LastName()") < 0,
                    "message should not contain get_LastName()\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("p.LastName") >= 0,
                    "message should contain p.LastName\nWas: " + e.Message);
            }
        }

        [Test]
        public void ErrorMessagesContainNameOfPropertySetterNotHiddenMethodOnInterface()
        {
            AssertErrorMessagesContainNameOfPropertySetterNotHiddenMethod(Mocks.NewNamedMock<IPersonRecord>("p"));
        }

        [Test, Class]
        public void ErrorMessagesContainNameOfPropertySetterNotHiddenMethodOnClass()
        {
            AssertErrorMessagesContainNameOfPropertySetterNotHiddenMethod(Mocks.NewNamedMock<PersonRecord>("p"));
        }

        private void AssertErrorMessagesContainNameOfPropertySetterNotHiddenMethod(IPersonRecord personRecord)
        {
            SkipVerificationForThisTest();
            
            Expect.Once.On(personRecord).SetProperty("FirstName").To("Fred");

            try
            {
                personRecord.LastName = "Bloggs";
            }
            catch (ExpectationException e)
            {
                Assert.IsTrue(e.Message.IndexOf("set_FirstName(\"Fred\")") < 0,
                    "message should not contain set_FirstName(\"Fred\")\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("p.FirstName = (equal to \"Fred\")") >= 0,
                    "message should contain p.FirstName = \"Fred\"\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("set_LastName(\"Bloggs\")") < 0,
                    "message should not contain set_LastName(\"Bloggs\")\nWas :" + e.Message);
                Assert.IsTrue(e.Message.IndexOf("p.LastName = \"Bloggs\"") >= 0,
                    "message should contain p.LastName = \"Bloggs\"\nWas: " + e.Message);

            }
        }
    }
}
